import json
import os
import random
import traceback
from time import time
from bs4 import BeautifulSoup
import requests
from app import cache
from app.views.common import *
from app.models import *
from flask import Blueprint
from flask import redirect, render_template, url_for, jsonify, send_from_directory

from app.views import utils
from sqlalchemy.exc import IntegrityError



main = Blueprint('main', __name__)


@main.route('/favicon.ico')
@cache.cached(timeout=60 * 60 * 24 * 100, key_prefix=make_cache_key)
def favicon():
    # 图标
    return redirect(to_https(url_for('static', filename='favicon.ico')))

@main.route('/sitemap.xml')
def static_from_sitemap():
    return send_from_directory(current_app.static_folder, request.path[1:])


@main.route('/robots.txt')
def static_from_root():
    return send_from_directory(current_app.static_folder, request.path[1:])


@main.route('/story.txt')
def static_from_story():
    return send_from_directory(current_app.static_folder, request.path[1:])


# 首页
@main.route('/')
@cache.cached(timeout=60 * 60 * 24 * 7, key_prefix=make_cache_key)
def index():
    blog_query = Blog.query
    category_list = Category.query.all()
    category_id = int(request.args.get('catetory', 0))
    if category_id:
        blog_query = blog_query.filter_by(categoryid=category_id)
    blog_count = blog_query.count()
    return render_template('index.html', title='首页', title_ch='魔都<br/>子沐', title_en='well-balanced heart',
                           id='header_index', blog_count=blog_count, category_list=category_list,
                           category_id=category_id)


# 获取博文列表
@main.route('/details/by/page')
@cache.cached(timeout=60 * 60 * 24 * 7, key_prefix=make_cache_key)
def blogByPage():
    returnData = {'status': 0}
    try:
        page = request.args.get('page', 0)
        category = request.args.get('category', 0)
        limit = request.args.get('limit', 10)
        blog_query = Blog.query
        if category and category != '0' and category != 0:
            blog_query = blog_query.filter_by(categoryid=category)
        blogList = blog_query.order_by(Blog.createTime.desc()).limit(limit).offset(
            (int(page) - 1) * int(limit)).all()
        returnData['data'] = [
            {'Id': one.id, 'title': one.title, 'imgSrc': one.imgSrc,
             'categoryName': one.categoryInfo.name,
             'content': '。'.join(html_to_plain_text(one.content).strip().split('\n')[:2])} for one in blogList]
        returnData['blog_count'] = blog_query.count()
    except Exception as e:
        returnData['status'] = 1
        returnData['msg'] = '数据异常' + str(e)
    return jsonify(returnData)


# 获取评论
@main.route('/get/reply/<int:Id>')
@cache.cached(timeout=60 * 60 * 24 * 7, key_prefix=make_cache_key)
def get_reply(Id):
    returnData = {'status': 0}
    try:
        page = request.args.get('page', 1)
        limit = request.args.get('limit', 10)
        replies = Reply.query.filter_by(blogid=Id).order_by(Reply.createtime.desc()).limit(limit).offset(
            (int(page) - 1) * int(limit)).all()
        returnData['data'] = [
            {'id': reply.id, 'nickname': reply.nickname,
             'createTime': reply.createtime.strftime('%Y/%m/%d'),
             'content': reply.content} for reply in replies]
        returnData['count'] = Reply.query.count()
    except Exception as e:
        returnData['status'] = 1
        returnData['msg'] = '数据异常' + str(e)
    return jsonify(returnData)


# 微语
@main.route('/whisper', methods=['POST', 'GET'])
@cache.cached(timeout=60 * 60 * 24 * 7, key_prefix=make_cache_key)
def whisper():
    loveTextCount = loveText.query.count()
    if request.method == 'POST':
        returnData = {'status': 0}
        try:
            page = request.form.get('page')
            limit = request.form.get('limit', 10)
            loveTextList = loveText.query.order_by(loveText.createTime.desc()).limit(limit).offset(
                (int(page) - 1) * int(limit)).all()
            returnData['data'] = [{'id': one.id, 'content': one.content, 'praisePoints': one.praisePoints,
                                   'time': str(one.createTime.time()),
                                   'date': one.createTime.date().strftime('%Y/%m/%d')} for one in loveTextList]
            returnData['whisper_count'] = loveTextCount
        except Exception as e:
            returnData['status'] = 1
            returnData['msg'] = '数据异常'
        return jsonify(returnData)
    return render_template('whisper.html', title='微语', title_ch='徽语', title_en="Sweet words of love",
                           id='header_whisper', whisper_count=loveTextCount)


# 微语点赞
@main.route('/praisePoints/whisper', methods=['POST'])
@cache.cached(timeout=60 * 60 * 24 * 7, key_prefix=make_cache_key)
def praisePoints_whisper():
    returnData = {'status': 0}
    try:
        id = request.form.get('id')
        state = request.form.get('state', 'false')
        if id:
            loveText_obj = loveText.query.get(id)
            if state == 'true':
                loveText_obj.praisePoints = loveText_obj.praisePoints - 1
            else:
                loveText_obj.praisePoints = loveText_obj.praisePoints + 1
            returnData['num'] = loveText_obj.praisePoints
            r = redis_connect()
            data = r.keys(pattern='*whisper*')
            if data:
                r.delete(*data)
    except Exception as e:
        returnData['status'] = 1
        returnData['msg'] = '数据异常'
    return jsonify(returnData)


# 留言
@main.route('/leacots', methods=['POST', 'GET'])
@cache.cached(timeout=60 * 60 * 24 * 7, key_prefix=make_cache_key)
def leacots():
    now_date = datetime.now().date().strftime('%Y/%m/%d')
    # 提交留言
    if request.method == 'POST':
        stateData = {'status': 1}
        try:
            nickname = request.form.get('nickname')
            email = request.form.get('email')
            content = request.form.get('content')
            message = Message()
            message.nickname = nickname
            message.email = email
            message.content = content
            message.createTime = datetime.now()
            db.session.add(message)
            db.session.commit()
            stateData['status'] = 0
            stateData['msg'] = '发布成功'
            r = redis_connect()
            data = r.keys(pattern='*leacots*')
            if data:
                r.delete(*data)
        except IntegrityError as error:
            print(traceback.format_exc())
            stateData['msg'] = '数据异常，请稍后重试'
        return jsonify(stateData)
    msg_count = Message.query.count()
    return render_template('leacots.html', title='留言', title_ch='留言', title_en="Leave your valuable suggestions",
                           id='header_leacots', now_date=now_date, msg_count=msg_count)


# 留言列表
@main.route('/get/leacots')
@cache.cached(timeout=60 * 60 * 24 * 7, key_prefix=make_cache_key)
def get_leacots():
    returnData = {'status': 0}
    try:
        page = request.args.get('page', 1)
        limit = request.args.get('limit', 10)
        messages = Message.query.order_by(Message.createTime.desc()).limit(limit).offset(
            (int(page) - 1) * int(limit)).all()
        returnData['data'] = [
            {'id': mess.Id, 'nickname': mess.nickname, 'createTime': mess.createTime.strftime('%Y/%m/%d'),
             'content': mess.content} for mess in messages]
        returnData['count'] = Message.query.count()
    except Exception as e:
        returnData['status'] = 1
        print(traceback.format_exc())
        returnData['msg'] = '数据异常'
    return jsonify(returnData)


# 相册
@main.route('/album', methods=['POST', 'GET'])
@cache.cached(timeout=60 * 60 * 24 * 7, key_prefix=make_cache_key)
def album():
    photo_num = Photos.query.count()
    if request.method == 'POST':
        returnData = {'status': 0}
        try:
            page = request.form.get('page')
            limit = request.form.get('limit', 10)
            photoList = Photos.query.order_by(Photos.createTime.desc()).limit(limit).offset(
                (int(page) - 1) * int(limit)).all()
            returnData['data'] = [{'Id': one.id, 'imgName': one.imgName, 'imgSrc': one.imgSrc,
                                   'createtime': one.createTime.date().strftime('%Y/%m/%d')} for one in photoList]
            returnData['photo_num'] = photo_num
        except Exception as e:
            returnData['status'] = 1
            returnData['msg'] = '数据异常'
        return jsonify(returnData)
    return render_template('album.html', title='相册', title_ch='相册', title_en="Life notes", id='header_album',
                           photo_new=Photos.query.order_by(Photos.createTime.desc()).first(), photo_num=photo_num)


# 博文
@main.route('/details/<int:Id>', methods=['POST', 'GET'])
@cache.cached(timeout=60 * 60 * 24 * 7, key_prefix=make_cache_key)
def details(Id):
    if request.method == 'POST':
        stateData = {'status': 1}
        try:
            # 评论
            reply = Reply()
            reply.blogId = Id
            reply.nickname = request.form.get('nickname')
            reply.email = request.form.get('email')
            reply.content = request.form.get('content')
            reply.createTime = datetime.now()
            db.session.add(reply)
            db.session.commit()
            stateData['status'] = 0
            stateData['msg'] = '发布成功'
            r = redis_connect()
            data = r.keys(pattern='*reply*')
            if data:
                r.delete(*data)
        except IntegrityError as error:
            stateData['msg'] = '数据异常，请稍后重试'
        return jsonify(stateData)
    blog = Blog.query.get(Id)
    # 浏览量自增
    blog.readingVolume = blog.readingVolume + 1
    db.session.add(blog)
    db.session.commit()
    last_blog = Blog.query.filter(Blog.id < Id).order_by(Blog.id.desc()).first()
    last_href = url_for('main.details', Id=last_blog.id) if last_blog and last_blog.id != Id else ''
    next_href = Blog.query.filter(Blog.id > Id).first()
    next_href = url_for('main.details', Id=next_href.id) if next_href and next_href.id != Id else ''
    return render_template('details.html', title='博文', title_ch='博文', title_en="Blog content", blog=blog,
                           last_href=last_href, next_href=next_href)


# 关于
@main.route('/about')
@cache.cached(timeout=60 * 60 * 24 * 7, key_prefix=make_cache_key)
def about():
    now_year = datetime.now().year
    about_list = System.query.filter(System.key.like('aboutme_%')).all()
    tool_list = Tool.query.order_by(Tool.percent.desc()).all()
    return render_template('about.html', title='关于', title_ch='关于', title_en="Information about me", id='header_about',
                           now_year=now_year, aboutme=about_list,
                           tool_list=tool_list)



# 加入日志记录
@main.after_request
def afterRequest(response):
    if 'admin' not in request.path:
        ip = str(request.headers.get('X-Real-Ip', request.remote_addr))
        if ip != '127.0.0.1':
            log_info = Log()
            log_info.path = request.path
            log_info.parm = json.dumps({'get': request.args.to_dict(), 'post': request.form.to_dict()})
            log_info.ip = ip
            log_info.state = request.method
            log_info.createTime = str(datetime.now())
            platform = request.user_agent.platform
            browser = request.user_agent.browser
            # 如果浏览器为空，那么platform设置为爬虫
            if not browser:
                browser = 'other'
                platform = 'spider'
            if not platform:
                platform = 'other'
            log_info.platform = platform  # 系统
            log_info.browser = browser  # 浏览器
            db.session.add(log_info)
            db.session.commit()
    return response


# 文件上传
@main.route('/upload', methods=['GET', 'POST'])
def upload():
    action = request.args.get('action')
    if request.method == 'POST' and action in ('uploadimage', 'uploadscrawl'):
        returnData = {'code': 0, 'msg': '', 'status': 0}
        try:
            f = request.files['file']
            # 文件文件路径
            basepath = 'zimu_file/'
            filepath = str(int(time())) + '/' + f.filename
            upload_path = basepath + filepath
            bucket.put_object(upload_path, f.read())
            bucket.put_object_acl(upload_path, oss2.OBJECT_ACL_PUBLIC_READ)
            type = ''
            if f.filename.split('.')[-1] in ['jpg', 'png', 'jpeg', 'gif', 'bmp', 'svg', 'webp']:
                type = '?x-oss-process=style/blog_img'
            returnData['data'] = {"src": 'https://oss.zimu.website/' + upload_path + type, 'title': f.filename}
            returnData['file_path'] = returnData['data']['src']
            returnData['status'] = 1
            returnData['success'] = True
        except Exception as e:
            current_app.logger.error(request.path + ',' + str(e))
            returnData['msg'] = '数据异常，请刷新后重试'
            returnData['success'] = False
        return jsonify(returnData)
    if action == 'config':
        # 解析JSON格式的配置文件
        # 这里使用PHP版本自带的config.json文件
        config_path = os.path.join(current_app.static_folder, 'ueditor', 'php',
                                   'config.json')
        with open(config_path, encoding='utf-8') as fp:
            result = json.loads(re.sub(r'\/\*.*\*\/', '', fp.read()))
        return json.dumps(result)
    if action == 'catchimage':
        returnData = {'state': 'SUCCESS'}
        source = request.form.get('source[]')
        # 文件文件路径
        basepath = 'zimu_file/'
        filepath = "catch/{}_{}.jpg".format(int(time()), int(random.random() * 100))
        upload_path = basepath + filepath
        bucket.put_object(upload_path, requests.get(source).content)
        bucket.put_object_acl(upload_path, oss2.OBJECT_ACL_PUBLIC_READ)
        type = '?x-oss-process=style/blog_img'
        file_list = [{"url": 'https://oss.zimu.website/' + upload_path + type, 'source': source, 'state': 'SUCCESS'}]
        returnData['list'] = file_list
        return jsonify(returnData)
    return redirect(url_for('main.index'))


# 上下文处理器
@main.app_context_processor
def main_commont():
    system_dict = {}
    try:
        system_list = System.query.filter(System.key.like('common_%')).all()
        system_dict = {item.key: item.value for item in system_list}
    except InvalidRequestError:
        db.session.rollback()
    return system_dict


# 新型冠状病毒感染肺炎疫情实时动态
@main.route('/monitor')
def monitor():
    return render_template('monitor.html', title='新型冠状病毒肺炎全国实时数据', title_ch='全国疫情实时跟踪',
                           title_en="National epidemic situation real-time tracking", id='header_monitor')


@main.route('/time')
def get_time():
    return utils.get_time()


@main.route('/c1')
@cache.cached(timeout=60 * 60 * 24, key_prefix=make_cache_key)
def get_c1_data():
    data = utils.get_c1_data()
    return jsonify({"confirm": float(data[0]), "suspect": float(data[1]), "heal": float(data[2]), "dead": float(data[3])})


@main.route('/c2')
@cache.cached(timeout=60 * 60 * 24, key_prefix=make_cache_key)
def get_c2_data():
    res = []
    for tup in utils.get_c2_data():
        res.append({"name": tup[0], "value": int(tup[1])})
    return jsonify({"data": res})


@main.route('/l1')
@cache.cached(timeout=60 * 60 * 24, key_prefix=make_cache_key)
def get_l1_data():
    data = utils.get_l1_data()
    day, confirm, suspect, heal, dead = [], [], [], [], []
    for item in data:
        day.append(item[0].strftime("%Y-%m-%d"))
        confirm.append(item[1])
        suspect.append(item[2])
        heal.append(item[3])
        dead.append(item[4])
    return jsonify({"day": day, "confirm": confirm, "suspect": suspect, "heal": heal, "dead": dead})


@main.route('/l2')
@cache.cached(timeout=60 * 60 * 24, key_prefix=make_cache_key)
def get_l2_data():
    data = utils.get_l2_data()
    day, confirm_add, suspect_add = [], [], []
    for a, b, c in data[7:]:
        day.append(a.strftime("%Y-%m-%d"))
        confirm_add.append(b)
        suspect_add.append(c)
    return jsonify({"day": day, "confirm_add": confirm_add, "suspect_add": suspect_add})


@main.route('/r1')
@cache.cached(timeout=60 * 60 * 24, key_prefix=make_cache_key)
def get_r1_data():
    data = utils.get_r1_data()
    city = []
    confirm = []
    for item in data:
        city.append(item[0])
        confirm.append(int(item[1]))
    return jsonify({"city": city, "confirm": confirm})


# 新闻页面
@main.route('/news')
@cache.cached(timeout=60 * 60 * 24 * 7)
def news():
    news_count = YuwuzhengNews.query.count()
    return render_template('news.html', id='header_news', title='IT快讯', title_ch='IT快讯', title_en="IT consulting",
                           news_count=news_count)


# 提取html中所有文本
def html_to_text(content):
    soup = BeautifulSoup(content, "html.parser")
    return soup.get_text()[:60] + '...'


# 新闻列表
@main.route('/news/list', methods=['POST', 'GET'])
@cache.cached(timeout=60 * 60 * 24, key_prefix=make_cache_key)
def news_list():
    result = {}
    try:
        post_data = json.loads(request.get_data(as_text=True))
        page = post_data.get('page', 1)
        limit = post_data.get('limit', '10')
        isdelete = post_data.get('isdelete', 1)
        if type(page) == str:
            if page.isnumeric():
                page = int(page)
            else:
                page = 1
        if type(limit) == str:
            if limit.isnumeric():
                limit = int(limit)
            else:
                limit = 10
        offset = (page - 1) * limit
        if isdelete:
            news_list = YuwuzhengNews.query.order_by(YuwuzhengNews.pubtime_date.desc()).filter_by(status=isdelete).limit(limit).offset(offset).all()
        else:
            news_list = YuwuzhengNews.query.order_by(YuwuzhengNews.pubtime_date.desc()).limit(limit).offset(offset).all()
        result['result'] = [{'id': item.id, 'title': item.title, 'content': html_to_text(item.content),
                             'createTime': "{} {}".format(item.pubtime_date, item.pubtime_time), 'status': item.status}
                            for item in news_list]
        result['success'] = True
        result['totalCount'] = YuwuzhengNews.query.count()
        result['message'] = ''
    except Exception as e:
        result['success'] = False
        result['message'] = str(e)
    return jsonify(result)


# 新闻详情
@main.route('/news/<int:Id>')
@cache.cached(timeout=60 * 60 * 24 * 7, key_prefix=make_cache_key)
def news_detail(Id):
    news = YuwuzhengNews.query.get(Id)
    return render_template('newsDetail.html', title='IT快讯内容', title_ch='IT快讯内容', title_en="IT consulting content",
                           news=news)


# 推广页面
@main.route('/promotion')
@cache.cached(timeout=60 * 60 * 24 * 7, key_prefix=make_cache_key)
def promotion():
    return render_template('promotion.html', title='推广页面', title_ch='推广页面', title_en="Promotion page",promotion_list=Promotion.query.all())


# 隐私政策
@main.route('/privacy-policy')
@cache.cached(timeout=60 * 60 * 24 * 7, key_prefix=make_cache_key)
def privacy_policy():
    return render_template('privacy-policy.html', title='使用声明', title_ch='使用声明', title_en="Use statement")
